package com.badou.project.rest.controllers;

import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.net.ntp.TimeStamp;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.badou.api.intermanage.interfacelogger.model.InterFaceLoggerEntity;
import com.badou.api.intermanage.interfacelogger.service.IInterFaceLoggerService;
import com.badou.brms.dictionary.DictionaryLib;
import com.badou.core.base.local.LogonCertificate;
import com.badou.core.base.local.LogonCertificateHolder;
import com.badou.designer.jdbc.CommonConsts;
import com.badou.designer.jdbc.common.util.HttpUtil;
import com.badou.designer.jdbc.common.web.BaseModuleAction;
import com.badou.designer.jdbc.common.web.form.BaseCommonSaveForm;
import com.badou.designer.jdbc.core.BlockChainConsts;
import com.badou.designer.jdbc.core.vo.BaseVO;
import com.badou.designer.module.GlobalConsts;
import com.badou.designer.module.design.ModuleCacheContainer;
import com.badou.designer.module.design.model.MdFieldEntity;
import com.badou.designer.module.design.model.MdFormEntity;
import com.badou.designer.module.design.model.MdModuleEntity;
import com.badou.plugins.cas.server.CasProperties;
import com.badou.project.rest.ReturnCodeEnum;
import com.badou.project.rest.service.IBaseRestService;
import com.badou.project.rest.vo.ApiReturnVO;
import com.badou.tools.common.Globals;
import com.badou.tools.common.PropertiesConfig;

/**
 * Restful API 实现
 * 
 * @author lps
 *
 */
@Controller
@RequestMapping(value = "/api/v1")
public class BaseRestController extends BaseModuleAction{

	/**
	 * 
	 */
	private static final long serialVersionUID = -8595166235669247995L;
	/**
	 * 模型
	 */
	protected MdModuleEntity moduleBean;
	/**
	 * 返回对象
	 */
	protected ApiReturnVO returnVO;

	protected static final String REQUEST_PARAMS_PREFIX = "SDdetail_";

	protected BaseCommonSaveForm custForm;

	@Autowired
	protected IBaseRestService baseRestService;
	@Autowired
	private IInterFaceLoggerService interFaceLoggerService;

	protected List<JSONObject> cusList = null;

	
	public MdModuleEntity getModuleBean() {
		return moduleBean;
	}

	public void setModuleBean(MdModuleEntity moduleBean) {
		this.moduleBean = moduleBean;
	}

	public BaseCommonSaveForm getCustForm() {
		return custForm;
	}

	public void setCustForm(BaseCommonSaveForm custForm) {
		this.custForm = custForm;
	}

	public void initModuleBean(String mdCode) {
		MdModuleEntity moduleBean = ModuleCacheContainer.getInstance()
				.getByCode(mdCode);
		baseRestService.initModule(moduleBean);
		this.moduleBean =moduleBean;
	}

	/**
	 * rest 获取get请求 获取
	 * 
	 * @param mdCode
	 *            模型的code
	 * @param model
	 * @return
	 */
	@ResponseBody
 	@RequestMapping(value = "/{mdCode}", method = RequestMethod.GET ,produces="text/html;charset=UTF-8")
	public ApiReturnVO doGet(@PathVariable String mdCode, ModelMap model,HttpServletRequest request) {
		returnVO = new ApiReturnVO();
		try{
			// 加载模型
			this.initModuleBean(mdCode);
			List<BaseVO> list = baseRestService.findAll();
			if (list != null) {
				returnVO.setReturnMsg(ReturnCodeEnum.SUCCESS.toString());
				this.convert(list, CommonConsts.STRATEGY_SINGEL);
				returnVO.setData(new ArrayList<Object>(cusList));
			} else {
				returnVO.setReturnMsg(ReturnCodeEnum.FAIL.toString());
			}
		}
		catch(Exception e)
		{
			logger.error(e);
			returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg()+e.getMessage());
			returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
		}
		finally{
			doUpdateLog(request);
		}
		return returnVO;
	}

	/**
	 * rest 获取post请求 新增
	 * 
	 * @param mdCode
	 *            模型的code
	 * @param model
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/{mdCode}", method = RequestMethod.POST ,produces="text/html;charset=UTF-8")
	public  ApiReturnVO doPost(@PathVariable String mdCode,HttpServletRequest request) {
		returnVO = new ApiReturnVO();
		try {
			this.initModuleBean(mdCode);
			if (custForm == null)
				custForm = new BaseCommonSaveForm();
			setCustFormProperties();
			/*if(StringUtils.isNotBlank(moduleBean.getRestBeforeSaveBean()))
			{
				Class<?> cls = Class.forName(moduleBean.getRestBeforeSaveBean());
				 Method m = cls.getDeclaredMethod("exeBeforeRestSave",new Class[]{BaseCommonSaveForm.class});  
				 custForm = (BaseCommonSaveForm) m.invoke(cls.newInstance(),custForm);
			}*/
			BaseVO vo = baseRestService.saveBaseVO(moduleBean, null, custForm, null);
			custForm.setId(vo.getId());
			restBlockchainSave(true);
		/*	if(StringUtils.isNotBlank(moduleBean.getRestAfterSaveBean()))
			{
				Class<?> cls = Class.forName(moduleBean.getRestAfterSaveBean());
				Method m = cls.getDeclaredMethod("exeAfterRestSave",new Class[]{BaseCommonSaveForm.class});  
				m.invoke(cls.newInstance(),custForm);
			}*/
			LogonCertificateHolder.clear();
			returnVO.setData(custForm.getReturnDetails());
			returnVO.setReturnMsg(ReturnCodeEnum.SUCCESS.getReturnMsg());
			returnVO.setReturnCode(ReturnCodeEnum.SUCCESS.getReturnCode());
		} catch (Exception e) {
			logger.error(e);
			returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg()+e.getMessage());
			returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
		}
		finally{
			doUpdateLog(request);
		}
		return returnVO;
	}

	/**
	 * rest 获取put请求 更新
	 * 
	 * @param mdCode
	 * @param id
	 * @param model
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/{mdCode}/{id}", method = RequestMethod.PUT,produces="text/html;charset=UTF-8")
	public ApiReturnVO doPut(@PathVariable String mdCode, @PathVariable String id,HttpServletRequest request) {
		returnVO = new ApiReturnVO();
		try {
			this.initModuleBean(mdCode);
			BaseVO vo = null;
			vo = baseRestService.get(id);
			if (custForm == null)
				custForm = new BaseCommonSaveForm();
			setCustFormProperties();
			custForm.setId(vo.getId());
			custForm.getDetails().put("id", new String[]{vo.getId()});
		/*	if(StringUtils.isNotBlank(moduleBean.getRestBeforeSaveBean()))
			{
				Class<?> cls = Class.forName(moduleBean.getRestBeforeSaveBean());
				 Method m = cls.getDeclaredMethod("exeBeforeRestSave",new Class[]{BaseCommonSaveForm.class});  
				 custForm = (BaseCommonSaveForm) m.invoke(cls.newInstance(),custForm);
			}*/
			custForm.setFormToEntityProperties(vo , true);
			baseRestService.saveBaseVO(moduleBean, null, custForm,vo);
			restBlockchainSave(false);
			/*if(StringUtils.isNotBlank(moduleBean.getRestAfterSaveBean()))
			{
				Class<?> cls = Class.forName(moduleBean.getRestAfterSaveBean());
				Method m = cls.getDeclaredMethod("exeAfterRestSave",new Class[]{BaseCommonSaveForm.class});  
				m.invoke(cls.newInstance(),custForm);
			}*/
			LogonCertificateHolder.clear();
			JSONObject result = this.getListForm(baseRestService.get(id));
			returnVO.setData(result);
			returnVO.setReturnMsg(ReturnCodeEnum.SUCCESS.getReturnMsg());
			returnVO.setReturnCode(ReturnCodeEnum.SUCCESS.getReturnCode());
		}
		catch(Exception e)
		{
			logger.error(e);
			returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg()+e.getMessage());
			returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
		}
		finally{
			doUpdateLog(request);
		}
		return returnVO;
	}

	/**
	 * rest 获取delete请求 删除
	 * 
	 * @param mdCode
	 * @param id
	 * @param model
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/{mdCode}/{id}", method = RequestMethod.DELETE,produces="text/html;charset=UTF-8")
	public ApiReturnVO doDelete(@PathVariable String mdCode,
			@PathVariable String id,HttpServletRequest request) {
		returnVO = new ApiReturnVO();
		try {
			this.initModuleBean(mdCode);
			if (custForm == null)
				custForm = new BaseCommonSaveForm();
			String msg = baseRestService.delete(moduleBean, id);
			if(StringUtils.isNotBlank(msg))
			{
				returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg()+msg);
				returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
			}
			else{
				returnVO.setReturnMsg(ReturnCodeEnum.SUCCESS.getReturnMsg());
				returnVO.setReturnCode(ReturnCodeEnum.SUCCESS.getReturnCode());
			}
		}
		catch(Exception e)
		{
			logger.error(e);
			returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg()+e.getMessage());
			returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
		}
		finally{
			doUpdateLog(request);
		}
		return returnVO;
	}

	/**
	 * rest 获取带id的get请求 通过id获取某个对象
	 * 
	 * @param mdCode
	 * @param id
	 * @param model
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/{mdCode}/{id}", method = RequestMethod.GET,produces="text/html;charset=UTF-8")
	public ApiReturnVO doGetWithId(@PathVariable String mdCode,
			@PathVariable String id, ModelMap model,HttpServletRequest request) {
		returnVO = new ApiReturnVO();
		try{
			// 加载模型
			this.initModuleBean(mdCode);
			BaseVO vo = baseRestService.get(id);
			if (vo != null) {
				JSONObject result = this.getListForm(vo);
				returnVO.setReturnMsg(ReturnCodeEnum.SUCCESS.toString());
				returnVO.setData(result);
			} else {
				returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
				returnVO.setReturnMsg(ReturnCodeEnum.FAIL.toString());
			}
		}
		catch(Exception e)
		{
			logger.error(e);
			returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg()+e.getMessage());
			returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
		}
		finally{
			doUpdateLog(request);
		}
		return returnVO;
	}
	
	/**
	 * rest 获取accessToken
	 * 
	 * @param mdCode
	 * @param id
	 * @param model
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/oauth2/token", method = RequestMethod.POST,produces="text/html;charset=UTF-8")
	public ApiReturnVO token() {
		returnVO = new ApiReturnVO();
		try{
			String getToken = PropertiesConfig.getPropValue("token.url");
			Map<String,String> map = new HashMap<String,String>();
			String appId =ServletActionContext.getRequest().getParameter("app_id");
			String appKey =ServletActionContext.getRequest().getParameter("app_key");
			map.put("APP_ID", appId);
			map.put("APP_KEY", appKey);
			net.sf.json.JSONObject jsonResult=HttpUtil.httpPost(getToken, map, false);
			if(jsonResult != null && jsonResult.getBoolean("hasOk"))
			{
				String message =jsonResult.get("message").toString();
				returnVO.setData(message);
				returnVO.setReturnMsg(ReturnCodeEnum.SUCCESS.getReturnMsg());
				returnVO.setReturnCode(ReturnCodeEnum.SUCCESS.getReturnCode());
			}
			else
			{
				returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg());
				returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
			}
		}
		catch(Exception e)
		{
			logger.error(e);
			returnVO.setReturnMsg(ReturnCodeEnum.FAIL.getReturnMsg()+e.getMessage());
			returnVO.setReturnCode(ReturnCodeEnum.FAIL.getReturnCode());
		}
	
		return returnVO;
	}
	
	@SuppressWarnings("unchecked")
	protected void setCustFormProperties() {
		Map<String, String[]> reqParams = new HashMap<String, String[]>();
		Map<String, String[]> srcParams = ServletActionContext.getRequest()
				.getParameterMap();
		String[] values = null;
		for (String key : srcParams.keySet()) {
			values = srcParams.get(key);
			if (key.startsWith(REQUEST_PARAMS_PREFIX)) {
				reqParams.put(key.substring(REQUEST_PARAMS_PREFIX.length()),
						values);
			} else {
				reqParams.put(key, values);
			}
		}
		if (reqParams.containsKey("id")) {
			this.custForm.setId(reqParams.get("id")[0]);
		}
		this.custForm.setDetails(reqParams);
	}

	/**
	 * 区块链保存
	 * 
	 * @throws Exception
	 */
	private void restBlockchainSave(Boolean isCreate) throws Exception {
		String apiUrl = this.moduleBean.getChaincodeModelType();
		String apiBaseUrl = DictionaryLib.getDictionaryValue("SEARCH_API");
		if (StringUtils.isBlank(apiUrl)) {
			return;
		}
		String name = DictionaryLib.getItemName(
				GlobalConsts.CHAINCODE_MODEL_TYPE, apiUrl);
		String modelName = apiUrl;
		net.sf.json.JSONObject jsonObj = new net.sf.json.JSONObject();
		net.sf.json.JSONObject child = null;
		List<MdFieldEntity> list = new ArrayList<MdFieldEntity>();
		list.addAll(this.moduleBean.getFields());
		if (isCreate) {
			jsonObj.put(BlockChainConsts.CHAINCODE_JSON_DEFAULT,
					BlockChainConsts.CHAINCODE_CLASS
							+ BlockChainConsts.CHAINCODE_CREATE_METHOD_PREFIX
							+ modelName);
		} else {
			jsonObj.put(BlockChainConsts.CHAINCODE_JSON_DEFAULT,
					BlockChainConsts.CHAINCODE_CLASS + modelName);
		}
		for (MdFieldEntity field : list) {
			MdFormEntity form = field.getForm();
			if (StringUtils.isBlank(form.getChaincodeModelName()))
				continue;
			String chaincodeModelName = form.getChaincodeModelName();
			if (chaincodeModelName.contains(Globals.SEPARATOR_POINT)) {
				String[] vals = chaincodeModelName.split("\\"
						+ Globals.SEPARATOR_POINT);
				String type = vals[0];
				String valName = vals[1];
				if (jsonObj.get(type) == null) {
					child = new net.sf.json.JSONObject();
				}
				if (child.get(BlockChainConsts.CHAINCODE_JSON_DEFAULT) == null) {
					// if(custForm.getDetails().get(field.getFieldName())!=null){
					child.put(
							BlockChainConsts.CHAINCODE_JSON_DEFAULT,
							BlockChainConsts.CHAINCODE_CLASS
									+ modelName
									+ BlockChainConsts.CHAINCODE_ATTRIBUTE_METHOD_SUFFIX);
					// }
				}
				String valType = form.getChaincodeModelType();
				if (!BlockChainConsts.EDIT_TYPE_SET.contains(valType)) {
					if (custForm.getDetails().get(field.getEntityName()) != null
							&& StringUtils.isNotBlank(custForm.getDetails()
									.get(field.getEntityName())[0])) {
						child.put(
								valName,
								valType
										+ custForm.getDetails().get(
												field.getEntityName())[0]);
					}
				} else {
					if (custForm.getDetails().get(field.getEntityName()) != null
							&& StringUtils.isNotBlank(custForm.getDetails()
									.get(field.getEntityName())[0])) {
						child.put(valName,
								custForm.getDetails()
										.get(field.getEntityName())[0]);
					}
				}
				jsonObj.put(type, child);
			} else {
				String valName = form.getChaincodeModelName();
				String valType = form.getChaincodeModelType();
				if (!BlockChainConsts.EDIT_TYPE_SET.contains(valType)) {
					if (custForm.getDetails().get(field.getEntityName()) != null
							&& StringUtils.isNotBlank(custForm.getDetails()
									.get(field.getEntityName())[0])) {
						child.put(
								valName,
								valType
										+ custForm.getDetails().get(
												field.getEntityName())[0]);
					}
				} else {
					if (custForm.getDetails().get(field.getEntityName()) != null
							&& StringUtils.isNotBlank(custForm.getDetails()
									.get(field.getEntityName())[0])) {
						jsonObj.put(valName,
								custForm.getDetails()
										.get(field.getEntityName())[0]);
					}
				}
			}
		}
		net.sf.json.JSONObject jsonResult = null;
		String url = null;
		// 进行保存
		if (isCreate) {
			url = apiBaseUrl + BlockChainConsts.CHAINCODE_CREATE_METHOD_PREFIX
					+ modelName;
			jsonResult = HttpUtil.httpPostWithJSON(url, jsonObj, false);

		} else {
			url = apiBaseUrl + modelName + "/"
					+ custForm.getDetails().get("code")[0];
			jsonResult = HttpUtil.httpPutRaw(url, jsonObj);
		}
		if (jsonResult != null) {
			if (isCreate) {
				String txId = jsonResult.getString("transactionId");
				if (StringUtils.isNotBlank(txId)) {
					custForm.getDetails().put("txId", new String[] { txId });
				}
			}
		}

	}
	protected void convert(List<BaseVO> list, Integer strategy) throws Exception{
		cusList = new ArrayList<JSONObject>();
		if(list != null && !list.isEmpty()){
			for(Object t : list){
				cusList.add(convert((BaseVO)t,strategy));
			}
		}
	}
	protected JSONObject convert(BaseVO t, Integer strategy) throws Exception{
		return super.getListForm((BaseVO)t);
	}
	
	private void doUpdateLog(HttpServletRequest request)
	{
		String logId =(String) request.getAttribute("logId");
		if(StringUtils.isNotBlank(logId))
		{
			LogonCertificate logon = new LogonCertificate("sa", "U00001", "超级管理员");
			LogonCertificateHolder.setLogonCertificate(logon);	
			InterFaceLoggerEntity logger = interFaceLoggerService.get(logId);
			Timestamp startTime = logger.getRequesttime();
			Date endTime = new Date();
			/*String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endTime);//将时间格式转换成符合Timestamp要求的格式.
			Timestamp time1 =Timestamp.valueOf(time);//把时间转换
*/			logger.setUpdateTime(endTime);
			//logger.setLateTime((time1.getTime()-startTime.getTime())+"ms");
			interFaceLoggerService.update(logger);
			LogonCertificateHolder.clear();
		}
	}
	
}
